# CCNCore::Scripting::commit.pm
# Copyright (C) 2006, 2007  Stephane Alnet
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 3
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program.  If not, see <http://www.gnu.org/licenses/>.
# 

#
# For more information visit http://carrierclass.net/
#
package CCNCore::Scripting::commit;
use strict; use warnings;
use CCN::Class;
use base qw(CCN::Class);


sub initialize($)
{
    my $self = shift;
    $self->{root} = shift;
    $self->{different} = {};
    $self->{force} = 0;
    $self->{debug} = 1;
}

sub root() { return shift->{root} }

sub commit_file($)
{
    my $self = shift;
    my $file = shift;
    $self->log ("CCN-DEBUG: commit_file $file\n") if $self->{debug};
    $self->die ("(INTERNAL) double-committing $file") if exists $self->{different}->{$file};
    $self->die ("commit_file: $self->{root}/$file does not exist") unless -e "$self->{root}/$file";
    if( -e $file )
    {
        system '/usr/bin/diff', '-b', '-E', '-B', '-q', $file, "$self->{root}/$file";
        $self->die ("Failed to execute diff $file $self->{root}/$file: $!") if $? == -1;
        $self->die ("Diff failed with signal ".($?&127))                    if $? & 127;
        $self->{different}->{$file} = $? >> 8;
        # back-up of the current file for this location
        unlink  "$file.previous"; # TBD Temporary (broken on dev lab)
        unlink "$self->{root}/$file.previous";
        # TBD rename() may not work across filesystems ('mv' does)
        rename $file, "$self->{root}/$file.previous";
        rename "$self->{root}/$file", $file;
    }
    else
    {
        rename "$self->{root}/$file", $file;
        $self->{different}->{$file} = 1;
    }
}

sub changed($)
{
    my $self = shift;
    my ($file) = @_;
    $self->log ("CCN-DEBUG: changed $file ?\n") if $self->{debug};

    $self->commit_file($file) unless exists $self->{different}->{$file};
    
    my $result = $self->{force} || (! exists $self->{different}->{$file}) || $self->{different}->{$file};

    $self->log ("CCN-DEBUG: $file has ".($result?'':'not ')."changed\n") if $self->{debug};
    return $result;
}

sub sub_if_changed($$)
{
    my $self = shift;
    my ($file,$command) = @_;
    $self->log ("CCN-DEBUG: sub_if_changed $file\n") if $self->{debug};

    $self->log ("CCN-DEBUG: sub_if_changed: execute\n"),
    $command->()
        if $self->changed($file);
}

sub run_if_changed
{
    my $self = shift;
    my $file = shift;

    $self->log ("CCN-DEBUG: run_if_changed $file @_\n") if $self->{debug};

    $self->log ("CCN-DEBUG: run_if_changed: run_command @_\n"),
    CCN::Scripting::run_command(@_)
        if $self->changed($file);
}

1;